package edu.vt.tcga.methylation.level1;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import edu.vt.tcga.HibernateUtil;

public class MethylationTable {

	private List<Methylation> values;

	// Accessor methods
	public List<Methylation> getValues() {
		return values;
	}
	public void setValues(List<Methylation> values) {
		this.values = values;
	}
	
	
	// Constructors
	public MethylationTable(){
		values = new ArrayList<Methylation>();
	}
	
	public MethylationTable(String filename){
		this();
		this.loadFromFile(filename);
	}

	// Utility functions
	public void loadFromFile(String filename){
		
		// Get current time
		long start = System.currentTimeMillis();
		
		System.out.println("Attempting to load expression genes analysis file: " + filename);
		
		try {
			BufferedReader in  = new BufferedReader(new FileReader(filename));
			String line = "";
			String delims = "\t";
	
			// Load Methylation
			// Get the Hybridization info.
			line = in.readLine();
			String[] tokens = line.split(delims);

			String hybrid = tokens[1];
			
			line = in.readLine();

			while( (line = in.readLine()) != null){
				tokens = line.split(delims);

				String compositeElement = tokens[0];	
				int methylatedSignalIntensity = 0;
				int mNumberBeads = 0;
				double mSTDERR = 0.0;	
				int unMethylatedSignalIntensity = 0;	
				int uNumberBeads = 0;
				double uSTDERR = 0.0;
				String negativeControlGrnAvgIntensity = tokens[7];
				double negativeControlGrnSTDERR = 0.0;
				String negativeControlRedAvgIntensity = tokens[9];	
				double negativeControlRedSTDERR = 0.0;
				double detectionPValue = 0.0;

				// Error checking
				try{
					methylatedSignalIntensity = Integer.parseInt(tokens[1]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format methylatedSignalIntensity. Value read in as " + 
							tokens[1] +
							". Setting to 0.");
				}

				try{
					mNumberBeads = Integer.parseInt(tokens[2]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format mNumberBeads. Value read in as " + 
							tokens[1] +
							". Setting to 0.");
				}

				try{
					mSTDERR = Double.parseDouble(tokens[3]);	
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format mSTDERR. Value read in as " + 
							tokens[1] +
							". Setting to 0.0.");
				}

				try{
					unMethylatedSignalIntensity = Integer.parseInt(tokens[4]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format unMethylatedSignalIntensity. Value read in as " + 
							tokens[1] +
							". Setting to 0.");
				}

				try{
					uNumberBeads = Integer.parseInt(tokens[5]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format uNumberBeads. Value read in as " + 
							tokens[1] +
							". Setting to 0.");
				}

				try{
					uSTDERR = Double.parseDouble(tokens[6]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format uSTDERR. Value read in as " + 
							tokens[1] +
							". Setting to 0.0.");
				}

				try{
					negativeControlGrnSTDERR = Double.parseDouble(tokens[8]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format negativeControlGrnSTDERR. Value read in as " + 
							tokens[1] +
							". Setting to 0.0.");
				}

				try{
					negativeControlRedSTDERR = Double.parseDouble(tokens[10]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format negativeControlRedSTDERR. Value read in as " + 
							tokens[1] +
							". Setting to 0.0.");
				}

				try{
					detectionPValue = Double.parseDouble(tokens[11]);
				}
				catch(NumberFormatException ne){
					System.out.println("Could not format detectionPValue. Value read in as " + 
							tokens[1] +
							". Setting to 0.0.");
				}

				Methylation methylation = new Methylation(compositeElement,	
						hybrid,	
						methylatedSignalIntensity,
						mNumberBeads,
						mSTDERR,	
						unMethylatedSignalIntensity,	
						uNumberBeads,
						uSTDERR,
						negativeControlGrnAvgIntensity,
						negativeControlGrnSTDERR,
						negativeControlRedAvgIntensity,	
						negativeControlRedSTDERR,	
						detectionPValue);
				
				values.add(methylation);
			}
			
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
		} 
		catch (IOException e) {
			e.printStackTrace();
		}
		
		// Get elapsed time in milliseconds
		long elapsedTimeMillis = System.currentTimeMillis()-start;
		double seconds = elapsedTimeMillis / 1000.0;
		
		System.out.println("Loaded methylation data in " + seconds + " seconds");
	}
	
	// Save the class out to the database
	public void saveToDatabase(){
		
		// Get current time
		long start = System.currentTimeMillis();
				
		try{
			Session session = HibernateUtil.getSession();
	        Transaction tx = session.beginTransaction();
	        int i = 0;
	        
	        for(Methylation methylation : this.getValues()){
	        	session.save(methylation);
		        
	            if ( i % 20 == 0 ) { //Same as the JDBC batch size
	                //flush a batch of inserts and release memory:
	                session.flush();
	                session.clear();
	            }
	            
		        i++;
	        }
	        
	        tx.commit();
	        session.close();
		}
		catch(Exception e){
			e.printStackTrace();
		}

		// Get elapsed time in milliseconds
		long elapsedTimeMillis = System.currentTimeMillis()-start;
		double seconds = elapsedTimeMillis / 1000.0;
		
		System.out.println("Saved methylation data in " + seconds + " seconds");
	}
	
}
